﻿#region Macro Definition
#define PARALLAX_USE
//#define NOT_PARALLAX
#define LEAP_USE

#endregion
#region Using Statement
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.Storage;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Audio;
using Microsoft.Xna.Framework.Media;
using Microsoft.Xna.Framework.Input;
using Microsoft.Xna.Framework.GamerServices;
using System.Collections.Generic;
using Leap;
using MonogameParallax;
//using GL_Core;
using BoundingBox2DCollision;
#endregion

namespace GameLove
{
    /// <summary>
    /// This is the main type for your game
    /// </summary>
    public class Game1 : Game
    {
        GraphicsDeviceManager graphics;
        SpriteBatch spriteBatch;
        SpriteFont text;
        Texture2D textureObj;
        Texture2D texturePlay;
        Texture2D texturePause;
        Texture2D texturePlug;
        Controller leapController;
        SingleLeaplisteners leapListener;
        SoundEffect sound;
        SoundEffectInstance soundIns;
        int score = 0;
        int activeFinger = 0;
        GameObject finger;
        GameObject menuPlay;
        GameObject menuPause;
        FPSCounterComponent fps;
        float _angle;
        float scale;
#if PARALLAX_USE
        List<ParallaxObject> parallaxObj;
        int count = 0;
#endif
        //Song sound;
        //SongCollection soundIns;

        public Game1()
        {
            graphics = new GraphicsDeviceManager(this);
            Content.RootDirectory = "Content";
        }

        /// <summary>
        /// Allows the game to perform any initialization it needs to before starting to run.
        /// This is where it can query for any required services and load any non-graphic
        /// related content.  Calling base.Initialize will enumerate through any components
        /// and initialize them as well.
        /// </summary>
        protected override void Initialize()
        {
            // TODO: Add your initialization logic here
            base.Initialize();

            leapController = new Controller();
            leapListener = new SingleLeaplisteners();
            leapController.AddListener(leapListener);

        }

        /// <summary>
        /// LoadContent will be called once per game and is the place to load
        /// all of your content.
        /// </summary>
        protected override void LoadContent()
        {
            // Create a new SpriteBatch, which can be used to draw textures.
            spriteBatch = new SpriteBatch(graphics.GraphicsDevice);

            // TODO: use this.Content to load your game content here
            
            
            text = Content.Load<SpriteFont>("font");

            textureObj = Content.Load<Texture2D>("pointer");
            texturePlay = Content.Load<Texture2D>("play");
            texturePause = Content.Load<Texture2D>("pause");
            texturePlug = Content.Load<Texture2D>("plug");
            

            fps = new FPSCounterComponent(this, spriteBatch, text);

            Components.Add(fps);
            menuPlay = new GameObject(texturePlay, new Vector2(Window.ClientBounds.Width / 2 - texturePlay.Width / 2 - 150, Window.ClientBounds.Height / 2 - texturePlay.Height / 2));
            menuPause = new GameObject(texturePause, new Vector2(Window.ClientBounds.Width / 2 - texturePause.Width / 2 + 150, Window.ClientBounds.Height / 2 - texturePause.Height / 2));
            menuPlay.color = Color.White;
            menuPause.color = Color.White;

            sound = Content.Load<SoundEffect>("MenuMusic_Loop");
            soundIns = sound.CreateInstance();

            finger = new GameObject(textureObj, Vector2.Zero);
            finger.color = Color.Snow;
#if PARALLAX_USE
            parallaxObj = new List<ParallaxObject>();
            parallaxObj.Add(new ParallaxObject(Content.Load<Texture2D>("pointer"), new Vector2(300, 300), 0.6f));
            parallaxObj.Add(new ParallaxObject(Content.Load<Texture2D>("pointer"), new Vector2(500, 500), 0.8f));
            parallaxObj.Add(new ParallaxObject(Content.Load<Texture2D>("pointer"), new Vector2(700, 700), 1.1f));
#endif
        }

        /// <summary>
        /// UnloadContent will be called once per game and is the place to unload
        /// all content.
        /// </summary>
        protected override void UnloadContent()
        {
            // TODO: Unload any non ContentManager content here
        }

        /// <summary>
        /// Allows the game to run logic such as updating the world,
        /// checking for collisions, gathering input, and playing audio.
        /// </summary>
        /// <param name="gameTime">Provides a snapshot of timing values.</param>
        protected override void Update(GameTime gameTime)
        {
            // TODO: Add your update logic here
            if(soundIns.State == SoundState.Playing)
                _angle += MathHelper.ToRadians(1);
            foreach (FingerPoint f in leapListener.fingerPoint)
            {
                if (f.isActive)
                {
                    float xObj = f.g_X * graphics.GraphicsDevice.Viewport.Width;
                    float yObj = f.g_Y * graphics.GraphicsDevice.Viewport.Height;
                    finger.Position.X = (int)xObj;
                    finger.Position.Y = (int)yObj;

                    if (finger.BoundingBox.Intersects(menuPlay.BoundingBox))
                    {
                        menuPlay.color = Color.BlueViolet;
                        if (soundIns.State == SoundState.Paused)
                            soundIns.Resume();
                        else
                            soundIns.Play();
                    }
                    else if (soundIns.State == SoundState.Playing)
                    {
                        menuPlay.color = Color.BlueViolet;
                    }
                    else
                    {
                        menuPlay.color = Color.White;
                    }

                    if (finger.BoundingBox.Intersects(menuPause.BoundingBox))
                    {
                        menuPause.color = Color.BlueViolet;
                        soundIns.Pause();
                    }
                    else if (soundIns.State == SoundState.Paused)
                    {
                        menuPause.color = Color.BlueViolet;
                    }
                    else
                    {
                        menuPause.color = Color.White;
                    }
                    
                }
            }

#if PARALLAX_USE
            KeyboardState kbState = Keyboard.GetState();

            if (GamePad.GetState(PlayerIndex.One).Buttons.Back == ButtonState.Pressed || Keyboard.GetState().IsKeyDown(Keys.Escape))
                Exit();

            //Get directional vector based on keyboard input
            Vector2 direction = Vector2.Zero;
            if (kbState.IsKeyDown(Keys.Up))
                direction = new Vector2(0, -1);
            else if (kbState.IsKeyDown(Keys.Down))
                direction = new Vector2(0, 1);
            if (kbState.IsKeyDown(Keys.Left))
                direction += new Vector2(-1, 0);
            else if (kbState.IsKeyDown(Keys.Right))
                direction += new Vector2(1, 0);


            direction += new Vector2(count++, 0);
            //Update backgrounds
            foreach (ParallaxObject bg in parallaxObj)
                bg.Update(gameTime, direction, GraphicsDevice.Viewport);
#endif
            base.Update(gameTime);
        }

        /// <summary>
        /// This is called when the game should draw itself.
        /// </summary>
        /// <param name="gameTime">Provides a snapshot of timing values.</param>
        protected override void Draw(GameTime gameTime)
        {
            GraphicsDevice.Clear(Color.BlanchedAlmond);

            // TODO: Add your drawing code here
#if PARALLAX_USE
            spriteBatch.Begin(SpriteSortMode.Deferred, null, SamplerState.LinearWrap, null, null);
            foreach (ParallaxObject bg in parallaxObj)
                bg.Draw(spriteBatch);
            spriteBatch.End();
#endif
            spriteBatch.Begin();
            string strFinger = "Please Connect to your Leap Motion Controller";
            if (leapController.IsConnected == false)
            {
                if (soundIns.State == SoundState.Playing)
                {
                    soundIns.Stop();
                }
                spriteBatch.Draw(texturePlug, new Vector2(Window.ClientBounds.Width / 2 - texturePlug.Width / 2, Window.ClientBounds.Height / 2 - 50), Color.White);
                spriteBatch.DrawString(text, strFinger, new Vector2(Window.ClientBounds.Width / 2 - text.MeasureString(strFinger).Length() / 2, Window.ClientBounds.Height / 2), Color.DarkRed);
            }
            else 
            {
                // Animation Text, Calculate the size of the text
                string strTextDeco = sound.Name;
                Vector2 textsize = text.MeasureString(strTextDeco);

                // Draw it lots of times
                for (int i = 25; i >= 0; i--)
                {
                    // For the final iteration, use black text;
                    // otherwise use white text with gradually increasing alpha levels
                    if (_angle == 0)
                    {
                        scale = 0;
                    }
                    else if (soundIns.State == SoundState.Stopped)
                    {
                        scale = 0;
                        this.Components.Clear();
                        this.Exit();
                    }
                    else
                    {
                        scale = 1 + (i / 7.0f);
                    }
                    spriteBatch.DrawString(text, strTextDeco, new Vector2(300, 300), Color.BurlyWood
                        , _angle == 0 ? 0 : MathHelper.ToRadians(_angle * ((i + 10) * 5f)),
                        textsize / 10, scale, SpriteEffects.None, 0);
           
                }
                string strText = string.Format("Music Title: {0}", sound.Name);
                spriteBatch.DrawString(text, strText, new Vector2(Window.ClientBounds.Width / 2 - text.MeasureString(strText).Length() / 2, Window.ClientBounds.Height / 2 - 150), Color.Black);
                menuPlay.Draw(spriteBatch);
                menuPause.Draw(spriteBatch);
                finger.Draw(spriteBatch);
            }
            spriteBatch.End();
            base.Draw(gameTime);
        }
    }
}
